﻿using System;
using System.Collections.Generic;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace CardInChina.Data.Entity
{
    public static class MySqlFunctions
    {
        [EdmFunction("CardInChina.Data.Entity.Store", "old_password")]
        public static string OldPassword(string data)
        {
            if (string.IsNullOrEmpty(data))
                throw new ArgumentNullException("data");

            return mysql_old_password(data);
        }

        [EdmFunction("CardInChina.Data.Entity.Store", "md5")]
        public static string MD5(string data)
        {
            if (string.IsNullOrEmpty(data))
                throw new ArgumentNullException("data");

            using (var x = new MD5CryptoServiceProvider())
            {
                var hash = x.ComputeHash(Encoding.ASCII.GetBytes(data));
                var buffer = new StringBuilder();
                foreach (byte b in hash)
                    buffer.Append(b.ToString("x2").ToLower());
                return buffer.ToString();
            }
        }

        /// <summary>
        /// http://www.yourhelpcenter.de/2009/06/mysql-alten-md5-hash-in-c-berechnen-16-stellig/
        /// </summary>
        private static string mysql_old_password(string data)
        {
            UInt32[] result = new UInt32[2];
            UInt32 nr = (UInt32)1345345333, add = (UInt32)7, nr2 = (UInt32)0x12345671;
            UInt32 tmp;

            char[] password = data.ToCharArray();
            int i;

            for (i = 0; i < data.Length; i++)
            {
                if (password[i] == ' ' || password[i] == '\t')
                    continue;

                tmp = (UInt32)password[i];
                nr ^= (((nr & 63) + add) * tmp) + (nr << 8);
                nr2 += (nr2 << 8) ^ nr;
                add += tmp;
            }

            result[0] = nr & (((UInt32)1 << 31) - (UInt32)1);
            UInt32 val = (((UInt32)1 << 31) - (UInt32)1);
            result[1] = nr2 & val;
            string hash = String.Format("{0:X}{1:X}", result[0], result[1]);
            return hash.ToLower();
        }

    }
}
